package SMS

import (
	"Push/config"
	"bytes"
	"encoding/binary"
	"fmt"
	"golang.org/x/text/encoding/unicode"
	"golang.org/x/text/transform"
	"log"
	"net"
	"os"
	"time"
)

// SGIPHeader 定义 SGIP 消息头
type SGIPHeader struct {
	TotalLength uint32
	CommandID   uint32
	SequenceID  [12]byte // 12 字节的 SequenceID
}

// SGIPResponse 定义 SGIP 响应消息
type SGIPResponse struct {
	Header  SGIPHeader
	Status  string // 状态码
	Reserve [8]byte
}

// SGIPBind 定义 SGIP BIND 消息
type SGIPBind struct {
	Header        SGIPHeader
	LoginType     uint8
	LoginName     [16]byte
	LoginPassword [16]byte
	Reserve       [8]byte
}

type SGIPUnbind struct {
	Header SGIPHeader
}

// SGIPSubmit 定义 SGIP SUBMIT 消息
type SGIPSubmit struct {
	Header           SGIPHeader
	SPNumber         [21]byte
	ChargeNumber     [21]byte
	UserCount        uint8
	UserNumber       [21]byte
	CorpID           [5]byte
	ServiceType      [10]byte
	FeeType          uint8
	FeeValue         [6]byte
	GivenValue       [6]byte
	AgentFlag        uint8
	MorelatetoMTFlag uint8
	Priority         uint8
	ExpireTime       [16]byte
	ScheduleTime     [16]byte
	ReportFlag       uint8
	TP_pid           uint8
	TP_udhi          uint8
	MessageCoding    uint8
	MessageType      uint8
	MessageLength    uint32
	MessageContent   []byte
	Reserve          [8]byte
}

// 定义命令ID常量
const (
	SGIP_BIND               = 0x00000001
	SGIP_UNBIND             = 0x00000002
	SGIP_SUBMIT             = 0x00000003
	SGIP_UNBIND_RESP        = 0x80000002
	SGIP_SUBMIT_RESP        = 0x80000003
	SGIP_DELIVER            = 0x4
	SGIP_DELIVER_RESP       = 0x80000004
	SGIP_REPORT             = 0x5
	SGIP_REPORT_RESP        = 0x80000005
	SGIP_ADDSP              = 0x6
	SGIP_ADDSP_RESP         = 0x80000006
	SGIP_MODIFYSP           = 0x7
	SGIP_MODIFYSP_RESP      = 0x80000007
	SGIP_DELETESP           = 0x8
	SGIP_DELETESP_RESP      = 0x80000008
	SGIP_QUERYROUTE         = 0x9
	SGIP_QUERYROUTE_RESP    = 0x80000009
	SGIP_ADDTELESEG         = 0xa
	SGIP_ADDTELESEG_RESP    = 0x8000000a
	SGIP_MODIFYTELESEG      = 0xb
	SGIP_MODIFYTELESEG_RESP = 0x8000000b
	SGIP_DELETETELESEG      = 0xc
	SGIP_DELETETELESEG_RESP = 0x8000000c
	SGIP_ADDSMG             = 0xd
	SGIP_ADDSMG_RESP        = 0x8000000d
	SGIP_MODIFYSMG          = 0xe
	SGIP_MODIFYSMG_RESP     = 0x0000000e
	SGIP_DELETESMG          = 0xf
	SGIP_DELETESMG_RESP     = 0x8000000f
	SGIP_CHECKUSER          = 0x10
	SGIP_CHECKUSER_RESP     = 0x80000010
	SGIP_USERRPT            = 0x11
	SGIP_USERRPT_RESP       = 0x80000011
	SGIP_TRACE              = 0x1000
	SGIP_TRACE_RESP         = 0x80001000
)

// Encode 对 SGIPBind 请求进行编码
func (req SGIPBind) Encode() ([]byte, error) {
	var buf bytes.Buffer

	// 计算消息总长度
	req.Header.TotalLength = uint32(binary.Size(req.Header) + binary.Size(req.LoginType) +
		binary.Size(req.LoginName) + binary.Size(req.LoginPassword) + binary.Size(req.Reserve))

	// 编码消息头
	if err := binary.Write(&buf, binary.BigEndian, req.Header.TotalLength); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.Header.CommandID); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.Header.SequenceID); err != nil {
		return nil, err
	}

	// 编码消息体
	if err := binary.Write(&buf, binary.BigEndian, req.LoginType); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.LoginName); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.LoginPassword); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.Reserve); err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

var sequenceNumber uint32

// 生成 SequenceID
func generateSequenceID(nodeID uint32) [12]byte {
	var sequenceID [12]byte

	// NodeID (4 bytes)
	binary.BigEndian.PutUint32(sequenceID[0:4], nodeID)

	// Timestamp (4 bytes)
	timestamp := uint32(time.Now().Unix())
	//fmt.Println(timestamp)
	binary.BigEndian.PutUint32(sequenceID[4:8], timestamp)

	// SequenceNumber (4 bytes)
	//sequenceNumber = uint32(timestamp) // 可以根据需要生成
	if sequenceNumber == 0 {
		sequenceNumber = timestamp * 10
	}
	sequenceNumber++
	binary.BigEndian.PutUint32(sequenceID[:12], sequenceNumber)
	fmt.Println(sequenceID)

	return sequenceID
}

func SGIPBindSend(provider *config.DefaultMailConfigProvider, conn net.Conn) {
	// 创建 SGIP BIND 请求消息
	req := SGIPBind{
		Header: SGIPHeader{
			CommandID:  SGIP_BIND,             // BIND 请求命令 ID
			SequenceID: generateSequenceID(1), // 生成 SequenceID
		},
		LoginType: 0x01, // 登录类型，0x01 表示客户端
	}

	// 填充 LoginName 和 LoginPassword
	copy(req.LoginName[:], []byte(provider.GetMailConfig().SMS.Sgip.LoginName))
	copy(req.LoginPassword[:], []byte(provider.GetMailConfig().SMS.Sgip.LoginPassword))

	// 初始化 Reserve 字段
	for i := 0; i < len(req.Reserve); i++ {
		req.Reserve[i] = 0x00
	}

	// 编码请求
	data, err := req.Encode()
	if err != nil {
		log.Printf("编码失败: %v\n", err)
		return
	}
	// 建立TCP链接
	//conn, err := net.Dial("tcp", provider.GetMailConfig().SMS.Sgip.SmgIpPort)
	//if err != nil {
	//	fmt.Printf("连接失败: %v\n", err)
	//	return
	//}
	//defer conn.Close()

	// 发送bind请求
	_, err = conn.Write(data)
	if err != nil {
		log.Printf("发送消息失败: %v\n", err)
		return
	}
	log.Println("Bind消息发送成功")

	// 接收响应
	buf := make([]byte, 1024)
	n, err := conn.Read(buf)
	if err != nil {
		log.Printf("接收响应失败: %v\n", err)
		return
	}

	// 解析响应
	log.Printf("接收到 BIND 响应: %x\n", buf[:n])
	// 打印状态码
	log.Println("BIND状态码:", buf[20])
	if len(provider.GetMailConfig().SMS.Sgip.UserNumber) > 0 {
		for _, UserNumber := range provider.GetMailConfig().SMS.Sgip.UserNumber {
			// 在 BIND 成功后，发送 SUBMIT 请求
			err = SGIPSubmitSend(conn, provider, UserNumber)
			//fmt.Printf("%v\n", req.Header.SequenceID)
			if err != nil {
				log.Printf("%s发送 SUBMIT 请求失败: %v\n", UserNumber, err)
				return
			}
		}
	}

	SGIPUnbindSend(conn)
	// 断开连接（defer conn.Close() 会自动关闭连接）
	log.Println("所有操作完成，连接已断开")
}

func (req SGIPSubmit) Encode() ([]byte, error) {
	var buf bytes.Buffer

	// 计算消息总长度
	req.Header.TotalLength = uint32(binary.Size(req.Header) + binary.Size(req.SPNumber) +
		binary.Size(req.ChargeNumber) + binary.Size(req.UserCount) + binary.Size(req.UserNumber) +
		binary.Size(req.CorpID) + binary.Size(req.ServiceType) + binary.Size(req.FeeType) +
		binary.Size(req.FeeValue) + binary.Size(req.GivenValue) + binary.Size(req.AgentFlag) +
		binary.Size(req.MorelatetoMTFlag) + binary.Size(req.Priority) + binary.Size(req.ExpireTime) +
		binary.Size(req.ScheduleTime) + binary.Size(req.ReportFlag) + binary.Size(req.TP_pid) +
		binary.Size(req.TP_udhi) + binary.Size(req.MessageCoding) + binary.Size(req.MessageType) +
		binary.Size(req.MessageLength) + len(req.MessageContent) + binary.Size(req.Reserve))
	// 编码消息头
	if err := binary.Write(&buf, binary.BigEndian, req.Header.TotalLength); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.Header.CommandID); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.Header.SequenceID); err != nil {
		return nil, err
	}
	// 编码消息体
	if err := binary.Write(&buf, binary.BigEndian, req.SPNumber); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.ChargeNumber); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.UserCount); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.UserNumber); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.CorpID); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.ServiceType); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.FeeType); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.FeeValue); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.GivenValue); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.AgentFlag); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.MorelatetoMTFlag); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.Priority); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.ExpireTime); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.ScheduleTime); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.ReportFlag); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.TP_pid); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.TP_udhi); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.MessageCoding); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.MessageType); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.MessageLength); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.MessageContent); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.Reserve); err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

// encodeMessage 根据 MessageCoding 编码短信内容
func encodeMessage(message string, messageCoding uint8) ([]byte, error) {
	switch messageCoding {
	case 8: // UTF-16BE
		encoder := unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM).NewEncoder()
		encoded, _, err := transform.Bytes(encoder, []byte(message))
		return encoded, err
	case 15: // GBK
		// 使用 golang.org/x/text/encoding/simplifiedchinese 包
		// 这里省略 GBK 编码的实现
		return []byte(message), nil
	default: // 默认使用 UTF-8
		return []byte(message), nil
	}
}

// getSGIPTime 生成 SGIP 协议的时间字符串（yymmddhhmmsstnnp 格式）
func getSGIPTime(t time.Time) [16]byte {
	var timeStr [16]byte

	// 格式化为 yymmddhhmmsstnnp
	timeFormat := t.Format("060102150405") + "032+"
	copy(timeStr[:], []byte(timeFormat))

	return timeStr
}

func SGIPSubmitSend(conn net.Conn, provider *config.DefaultMailConfigProvider, UserNumber string) error {
	// 短信内容
	var message string
	if provider.GetMailConfig().ContentS.Type == 0 {
		message = provider.GetMailConfig().SMS.Sgip.Message
	} else if provider.GetMailConfig().ContentS.Type == 1 {
		msgPath := provider.GetMailConfig().ContentS.File
		messageContent, err := os.ReadFile(msgPath)
		message = string(messageContent)
		if err != nil {
			return fmt.Errorf("短信：读取文件失败 %s: %w", msgPath, err)
		}
	} else if provider.GetMailConfig().ContentS.Type == 2 {
		message = provider.GetMailConfig().ContentS.Content
	}

	messageCoding := uint8(8) // UTF-16BE 编码

	// 编码短信内容
	messageContent, err := encodeMessage(message, messageCoding)
	if err != nil {
		log.Printf("编码短信内容失败: %v\n", err)
		return err
	}
	messageLength := uint32(len(messageContent))

	// 获取当前时间
	//now := time.Now()
	//expireTime := getSGIPTime(now.Add(24 * time.Hour))
	//
	//// 定义 ScheduleTime（短消息定时发送的时间）
	//scheduleTime := getSGIPTime(now) // 立即发送

	// 创建 SGIP SUBMIT 请求消息
	req := SGIPSubmit{
		Header: SGIPHeader{
			CommandID:  SGIP_SUBMIT,           // SUBMIT 请求命令 ID
			SequenceID: generateSequenceID(2), // 生成 SequenceID
		},
		UserCount: 1, // 用户数量
		FeeType:   1, // 计费类型
		//FeeValue:   0, // 收费值
		//GivenValue: 0,               // 赠送花费
		AgentFlag:        1, // 代收费标志，0：应收；1：实收，字符
		MorelatetoMTFlag: 3, // 引起 MT 消息的原因
		Priority:         1,
		ReportFlag:       1, // 需要状态报告
		//TP_pid:           1,                // GSM 协议类型
		//TP_udhi:          1,                // GSM 协议类型
		MessageCoding:  messageCoding,  // 消息编码格式
		MessageType:    0,              // 消息类型（普通短信）
		MessageLength:  messageLength,  // 消息长度
		MessageContent: messageContent, // 消息内容
		//ExpireTime:     expireTime,     // 短消息寿命的终止时间
		//ScheduleTime:   scheduleTime,   // 短消息定时发送的时间
	}

	// 填充固定长度字段
	copy(req.SPNumber[:], []byte(provider.GetMailConfig().SMS.Sgip.SPNumber))
	copy(req.ChargeNumber[:], []byte(provider.GetMailConfig().SMS.Sgip.ChargeNumber))
	copy(req.UserNumber[:], []byte(UserNumber))
	copy(req.CorpID[:], []byte(provider.GetMailConfig().SMS.Sgip.CorpID))
	copy(req.ServiceType[:], []byte(provider.GetMailConfig().SMS.Sgip.ServiceType))

	// 初始化 Reserve 字段
	for i := 0; i < len(req.Reserve); i++ {
		req.Reserve[i] = 0x00
	}

	// 编码请求
	data, err := req.Encode()
	if err != nil {
		log.Printf("编码失败: %v\n", err)
		return err
	}

	// 发送 SUBMIT 请求
	_, err = conn.Write(data)
	if err != nil {
		log.Printf("发送 SUBMIT 请求失败: %v\n", err)
		return err
	}
	log.Println(UserNumber, "SUBMIT 请求发送成功")
	// 接收响应
	buf := make([]byte, 1024)
	n, err := conn.Read(buf)
	if err != nil {
		log.Printf("接收响应失败: %v\n", err)
		return err
	}
	log.Printf("接收到 SUBMIT 响应: %x\n", buf[:n])
	// 打印状态码
	log.Println("SUBMIT状态码:", buf[20])
	return nil
}

func (req SGIPUnbind) Encode() ([]byte, error) {
	var buf bytes.Buffer

	// 计算消息总长度
	req.Header.TotalLength = uint32(binary.Size(req.Header))
	// 编码消息头
	if err := binary.Write(&buf, binary.BigEndian, req.Header.TotalLength); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.Header.CommandID); err != nil {
		return nil, err
	}
	if err := binary.Write(&buf, binary.BigEndian, req.Header.SequenceID); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func SGIPUnbindSend(conn net.Conn) error {
	// 创建 SGIP SUBMIT 请求消息
	req := SGIPUnbind{
		Header: SGIPHeader{
			CommandID:  SGIP_UNBIND,           // SUBMIT 请求命令 ID
			SequenceID: generateSequenceID(3), // 生成 SequenceID
		},
	}

	// 编码请求
	data, err := req.Encode()
	if err != nil {
		log.Printf("编码失败: %v\n", err)
		return err
	}
	// 发送UNBIND
	_, err = conn.Write(data)
	if err != nil {
		log.Printf("发送 UNBIND 请求失败: %v\n", err)
		return err
	}
	log.Println("UNBIND 请求发送成功")
	// 接收响应
	buf := make([]byte, 1024)
	n, err := conn.Read(buf)
	if err != nil {
		log.Printf("接收响应失败: %v\n", err)
		return err
	}
	log.Printf("接收到 UNBIND 响应: %x\n", buf[:n])
	return nil
}
